﻿#include "StdClassFun.h"
#include <cstring>
#include <qapplication.h>
#include <QMutexLocker>
#include <QDir>
#include <QProcess>
//#include <qdebug.h>
/***********************************************/
// 年份
static int year;
// 月份
static int month;
// 天数
static int day;
// 小时
static int hour;
// 分钟
static int minute;
// 秒钟
static int second;
// 毫秒
static int msec;

/***********************************************/
/***********************************************/


static QString freeBytesAvailableKey = "可用空间";
static QString totalNumberOfBytesKey = "总空间";
static QString totalNumberOfFreeBytes = "剩余空间";

/***********************************************/
/***********************************************/

// 正则过滤器
static QRegExp matchRegExp;
// 一般过滤器
static QString matchNormalExp;
// 一般匹配状态
// 0 为存在则匹配
// 1 为尾匹配
static int matchStatus = 0;
/***********************************************/
/***********************************************/

// 文本格式化
static QString fileOutFormStr;
// 日期格式化
static QString changeTimeDataTimeForm = "yyyy-MM-dd";

/***********************************************/
/***********************************************/

static QVector<QObject*> threadVector;

/***********************************************/
/***********************************************/
// id 锁
static QMutex showQueueMutex;

/***********************************************/

QString& getFreeBytesAvailableKey( ) {
	return freeBytesAvailableKey;
}

QString& getTotalNumberOfBytesKey( ) {
	return totalNumberOfBytesKey;
}

QString& getTotalNumberOfFreeBytes( ) {
	return totalNumberOfFreeBytes;
}

QRegExp* getRegExpFilter( ) {
	if( matchRegExp.isValid( ) )
		return &matchRegExp;
}

void setRegExpFilter(const QString& reg_exp) {
	matchRegExp.setPattern(reg_exp);
}

void setRegExpFilter(const QRegExp& reg_exp_body) {
	matchRegExp = reg_exp_body;
}

int doRegExpFilter(const QString& regExpStr) {
	if( matchRegExp.isValid( ) )
		return matchRegExp.indexIn(regExpStr);
	return -1;
}

int doRegExpFilter(const QString& regExpStr
	, const QString& regExp) {
	QRegExp matchRegExp(regExp);
	if( matchRegExp.isValid( ) )
		return matchRegExp.indexIn(regExpStr);
	return -1;
}

int doRegExpFilter(const QString& regExpStr
	, const QRegExp& regExp) {
	if( regExp.isValid( ) )
		return regExp.indexIn(regExpStr);
	return -1;
}

int findStr(const QString& srcourceSrtr
	, const QString& targetStr
	, int& offset
	, const int& sourcesSize
	, const int& targetSize
	, const qint64& endIndex) {
	int targetIndex = 0;
	while( sourcesSize > offset ) {
		if( offset > endIndex )
			return -1;
		if( srcourceSrtr[offset] == targetStr[targetIndex] ) {
			while( targetIndex < targetSize ) {
				if( srcourceSrtr[offset] != targetStr[targetIndex] )
					break;
				++targetIndex;
				if( targetIndex == targetSize )
					return offset - targetSize + 1;
				++offset;
			}
			targetIndex = 0;
		}
		++offset;
	}
	return -1;
}

int findStr(const QString& srcourceSrtr
	, const QString& targetStr
	, int offset) {
	auto&& sourcesSize = srcourceSrtr.size( );
	auto&& targetSize = targetStr.size( );
	if( sourcesSize - offset <= 0 )
		return -1;
	if( ( sourcesSize < targetSize ) && targetSize == 0 )
		return 0;
	int targetIndex = 0;
	auto&& completerStr = sourcesSize - targetSize + 1;
	if( completerStr > sourcesSize * 2.0 / 5 ) {
		// 最大可比较
		return findStr(srcourceSrtr, targetStr, offset, sourcesSize, targetSize, completerStr);
	}
	while( sourcesSize > offset ) {
		if( srcourceSrtr[offset] == targetStr[targetIndex] ) {
			if( srcourceSrtr[offset] == targetStr[targetIndex] ) {
				if( sourcesSize - offset < targetSize )
					return -1;
				++targetIndex;
				if( targetIndex == targetSize )
					return offset - targetSize + 1;
			} else
				targetIndex = 0;
		}
		++offset;
	}
	return -1;
}

int findStr(const QString& srcourceSrtr
	, const QString& targetStr) {
	return findStr(srcourceSrtr, targetStr, 0);
}

int findStr(const char* srcourceSrtr
	, const char* targetStr
	, int offset) {
	auto&& sourcesSize = std::strlen(srcourceSrtr);
	auto&& targetSize = std::strlen(targetStr);
	if( sourcesSize - offset <= 0 )
		return -1;
	if( ( sourcesSize > targetSize ) && targetSize == 0 )
		return 0;
	int targetIndex = 0;
	// 最大可比较
	auto&& completerStr = sourcesSize - targetSize + 1;
	while( sourcesSize > offset ) {
		if( offset > completerStr )
			return -1;
		if( srcourceSrtr[offset] == targetStr[targetIndex] ) {
			while( targetIndex < targetSize ) {
				if( srcourceSrtr[offset] != targetStr[targetIndex] )
					break;
				++targetIndex;
				if( targetIndex == targetSize )
					return offset - targetSize + 1;
				++offset;
			}
			targetIndex = 0;
		}
		++offset;
	}
	return -1;
}

void threadVectorAppendObj(QObject* object) {
	if( object != Q_NULLPTR )
		threadVector.append(object);
}

bool threadVectorReleaseObj(QObject* object) {
	if( object != Q_NULLPTR )
		threadVector.removeOne(object);
	if( threadVector.isEmpty( ) )
		return true;
	return false;
}

int findStr(const char* srcourceSrtr
	, const char* targetStr) {
	return findStr(srcourceSrtr, targetStr, 0);
}

bool doNormalFilter(const QString& normalStr) {
	// 匹配 *
	int indexOf = matchNormalExp.length( ) - 1;
	if( indexOf != -1 ) {
		// 存在 *
		QStringList list = matchNormalExp.split("*");
		list.removeAll("");
		if( list.size( ) == 0 )
			return true;
		if( matchNormalExp.at(indexOf) == '*' )
			// 存在尾巴 *，则使用任意匹配
			matchStatus |= 1;
		if( matchNormalExp.at(0) != '*' )
			// 不存在首部 *，则使用首匹配
			matchStatus |= 2;
		const QString at = list.at(0);
		int nextInde = 0;
		auto&& normalStrLen = normalStr.length( );
		for( int index = 0;index < list.size( );++index ) {
			const QString string = list.at(index);
			nextInde = findStr(normalStr, string, nextInde);
			if( nextInde == -1 || ( index == 0 && matchStatus & 2 && nextInde != 0 ) )
				return false;
			nextInde += string.length( ) - 1;
		}
		QString mid = normalStr.mid(nextInde);
		QString& string = list.last( );
		if( !( matchStatus & 1 ) )
			if( mid.length( ) != string.length( ) )
				return false;
		return true;
	}
	if( normalStr.indexOf(matchNormalExp) != -1 )
		return true;
	return false;
}

bool doNormalFilter(const QString& normalStr
	, const QString& matchNormalExp) {
	// 匹配 *
	int indexOf = matchNormalExp.indexOf("*");
	if( indexOf != -1 ) {
		// 存在 *
		QStringList list = matchNormalExp.split("*");
		list.removeAll("");
		if( indexOf == 0 )
			// 存在尾巴 *，则使用任意匹配
			matchStatus |= 1;
		if( matchNormalExp.at(0) != '*' )
			// 不存在首部 *，则使用首匹配
			matchStatus |= 2;
		const QString at = list.at(0);
		const QString chars = normalStr;
		int nextInde = 0;
		for( int index = 0;index < list.size( );++index ) {
			const QString string = list.at(index);
			nextInde = findStr(normalStr, string, nextInde);
			if( nextInde == -1 || ( index == 0 && matchStatus & 2 && nextInde != 0 ) )
				return false;
		}
		QString mid = normalStr.mid(nextInde);
		QString& string = list.last( );
		if( !( matchStatus & 1 ) )
			if( mid.length( ) != string.length( ) )
				return false;
		return true;
	}
	if( normalStr.indexOf(matchNormalExp) != -1 )
		return true;
	return false;
}

void setNormalFilter(const QString& FilterSuffix) {
	matchNormalExp = FilterSuffix;
}

QString* getNormalFilter( ) {
	return &matchNormalExp;
}

int doFilter(const QString& completerStr
	, int filter_Type) {
	// 匹配一次
	switch( filter_Type ) {
		case 1 :
			if( doNormalFilter(completerStr) )
				return 1;
			if( doRegExpFilter(completerStr) != -1 )
				return 2;
			return -1;
		case 2 :
			if( doRegExpFilter(completerStr) != -1 )
				return 2;
			if( doNormalFilter(completerStr) )
				return 1;
			return -1;
		case 0 :
			if( doNormalFilter(completerStr) )
				return 1;
			if( doRegExpFilter(completerStr) )
				return 2;
			return -1;
	}
	return -1;
}

void setFileOutForm(const QString& str) {
	fileOutFormStr = str;
}

QString* getFileOutForm( ) {
	return &fileOutFormStr;
}

QString doFileOutForm(const QString& filePath) {
	QFileInfo info(filePath);
	QString targetStr = fileOutFormStr;
	QString absoluteFilePath = info.absoluteFilePath( );
	if( info.isFile( ) ) {
		QString fileName = info.fileName( );
		targetStr = targetStr.replace("%fileName%", fileName);
		targetStr = targetStr.replace("%baseName%", info.baseName( ));
		targetStr = targetStr.replace("%absolutePath%", info.absolutePath( ));
		targetStr = targetStr.replace("%suffix%", info.suffix( ));
	} else {
		targetStr = targetStr.replace("%fileName%", absoluteFilePath);
	}
	targetStr = targetStr.replace("%absoluteFileName%", absoluteFilePath);
	targetStr = targetStr.replace("\\n", "\n");
	targetStr = targetStr.replace("\\t", "\t");
	targetStr = targetStr.replace("\\r\\n", "\n");
	QString string = info.metadataChangeTime( ).toString(changeTimeDataTimeForm);
	targetStr = targetStr.replace("%changeDateTime%", string);
	return targetStr;
}

void setFileOutDateTimeForm(const QString& str) {
	changeTimeDataTimeForm = str;
}

QString* getFileOutDateTimeForm( ) {
	return &changeTimeDataTimeForm;
}

qreal getGb(qint64 HighPart
	, qint64 LowPart) {
	return ( HighPart << 2 ) + ( LowPart ) / 1024.0 / 1024.0 / 1024.0;
}

QMutex* getShowMutexObj( ) {
	return &showQueueMutex;
}

QDateTime currentDateTimeToCompleterDateTime(QDateTime& changeTime) {
	return changeTime.addYears(year).addMonths(month).addDays(day).addSecs(hour * 60 * 60 + minute * 60 + second).addMSecs(msec);
}

QDateTime getCompleterDateTime( ) {
	return QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec));
}

void setCompleterDateTime(QDateTime& changeTime) {
	auto&& date = changeTime.date( );
	auto&& time = changeTime.time( );
	year = date.year( );
	month = date.month( );
	day = date.day( );
	hour = time.hour( );
	minute = time.minute( );
	second = time.second( );
	msec = time.msec( );
}

void setCompleterDate(QDate& changeTime) {
	year = changeTime.year( );
	month = changeTime.month( );
	day = changeTime.day( );
}

void setCompleterTime(QTime& changeTime) {
	hour = changeTime.hour( );
	minute = changeTime.minute( );
	second = changeTime.second( );
	msec = changeTime.msec( );
}

void addCompleterTime(QTime& changeTime) {
	hour = changeTime.hour( ) + hour;
	minute = changeTime.minute( ) + minute;
	second = changeTime.second( ) + second;
	msec = changeTime.msec( ) + msec;
}

void addCompleterDate(QDate& changeTime) {
	year = changeTime.year( ) + year;
	month = changeTime.month( ) + month;
	day = changeTime.day( ) + day;
}

void setCompleterDateYear(int paramYear) {
	year = paramYear;
}

void setCompleterDateMonth(int paramMonth) {
	month = paramMonth;
}

void setCompleterDateDay(int paramDay) {
	day = paramDay;
}

void setCompleterTimeHour(int paramHour) {
	hour = paramHour;
}

void setCompleterTimeMinute(int paramMinute) {
	minute = paramMinute;
}

void setCompleterTimeSecond(int paramSecond) {
	second = paramSecond;
}

void setCompleterTimeMsec(int paramMsec) {
	msec = paramMsec;
}

void addCompleterDateYear(int paramYear) {
	year += paramYear;
}

void addCompleterDateMonth(int paramMonth) {
	month += paramMonth;
}

void addCompleterDateDay(int paramDay) {
	day += paramDay;
}

void addCompleterTimeHour(int paramHour) {
	hour += paramHour;
}

void addCompleterTimeMinute(int paramMinute) {
	minute += paramMinute;
}

void addCompleterTimeSecond(int paramSecond) {
	second += paramSecond;
}

void addCompleterTimeMsec(int paramMsec) {
	msec += paramMsec;
}

QStringList doFiles(QString* filePath
	, QString file
	, int fileOpterator
	, QVector<QString>* destPtahVector) {
	static QMutex mutex;
	QStringList outLogStr;
	// 拷贝
	QDir dir;
	QFileInfo keyInfo(file);
	QString absoluteFilePath;
	if( keyInfo.exists( ) && keyInfo.isFile( ) ) {
		absoluteFilePath = keyInfo.absoluteFilePath( );
		file = "/" + file.remove(0, filePath->length( ));
		for( auto& targetPath : *destPtahVector ) {
			const QString newName = targetPath + file;
			keyInfo.setFile(newName);
			QString absolutePath = keyInfo.absolutePath( );
			QMutexLocker locker(&mutex);
			dir.mkpath(keyInfo.absolutePath( ));
			locker.unlock( );
			if( !QFile::copy(absoluteFilePath, newName) )
				outLogStr << absoluteFilePath << QString("\n\t复制失败\n");
			else
				outLogStr << QString(absoluteFilePath + "\n\t复制到\n" + newName + "\n");
		}
	}
	if( fileOpterator == 1 && !absoluteFilePath.isEmpty( ) ) {
		if( QFile::remove(absoluteFilePath) ) {
			outLogStr << absoluteFilePath << QString("\n\t删除成功\n");
		} else
			outLogStr << QString(absoluteFilePath + "\n\t删除失败\n");
	}
	return outLogStr;
}

QHash<QString, QVector<QString>> initParameters(int& argc
	, char** argv
	, QString& currentExeName
	, std::function<void (QHash<QString, QVector<QString>>*)> callBack) {
	QHash<QString, QVector<QString>> result;
	if( argc > 1 ) {
		currentExeName = QString::fromLocal8Bit(argv[0]);
		QVector<QString> exec;
		for( int index = 1;index < argc;++ index ) {
			QString paramerBuff = QString::fromLocal8Bit(argv[index]);
			if( paramerBuff[0] == '-' ) {
				QVector<QString> value = result.value(paramerBuff);
				for( ++index;index < argc;++index ) {
					QString argBuffQstring = QString::fromLocal8Bit(argv[index]);
					if( argBuffQstring[0] != '-' )
						value.append(argBuffQstring);
					else {
						--index;
						break;
					}
				}
				result.insert(paramerBuff, value);
			} else {
				exec.append(paramerBuff);
			}
		}
		result.insert(currentExeName, exec);
	}
	callBack(&result);
	return result;
}

// 移除单行注释
QString removeComment(const QByteArray& bytes) {
	QString fileCen(bytes);
	for( int commentSatrtIndex = fileCen.indexOf("//");commentSatrtIndex != -1;commentSatrtIndex = fileCen.indexOf("//") ) {
		int commentEndIndex = fileCen.indexOf("\n", commentSatrtIndex);
		fileCen = fileCen.remove(commentSatrtIndex, commentEndIndex - commentSatrtIndex);
	}
	return fileCen;
}

qint64 getSeepDate(QDateTime& left
	, QDateTime& right) {
	auto&& leftDate = left.date( );
	auto&& rightDate = right.date( );
	// left 闰年
	auto&& leftYear = leftDate.year( );
	int leftLeap = 0;
	if( leftYear % 4 == 0 || leftYear % 400 == 0 && leftYear % 100 != 0 )
		leftLeap = 1;
	// right 闰年
	auto&& rightYear = rightDate.year( );
	int rightLeap = 0;
	if( rightYear % 4 == 0 || rightYear % 400 == 0 && rightYear % 100 != 0 )
		rightLeap = 1;
	// 返回结果
	return ( leftYear * 365 + leftYear * leftLeap ) - ( rightYear * 365 + rightYear * rightLeap );
}

qint64 timeToMsec(QTime& rightTime) {
	int hour = ( rightTime.hour( ) > 0 ) ? rightTime.hour( ) : 0;
	int minute = ( rightTime.minute( ) > 0 ) ? rightTime.minute( ) : 0;
	int second = ( rightTime.second( ) > 0 ) ? rightTime.second( ) : 0;
	int msec = ( rightTime.msec( ) > 0 ) ? rightTime.msec( ) : 0;
	return hour * 59 * 59 * 999 + minute * 59 * 999 + second * 999 + msec;
}

qint64 getSeepTime(QTime& left
	, QTime& right) {
	return timeToMsec(left) - timeToMsec(right);
}

qint64 getSeepTime(QDateTime& left
	, QDateTime& right) {
	auto&& leftTime = left.time( );
	auto&& leftMs = timeToMsec(leftTime);
	auto&& rightTime = right.time( );
	auto&& rightMs = timeToMsec(rightTime);
	return leftMs - rightMs;
}

int comppareTime(QDateTime& left
	, QDateTime& right) {
	auto&& leftTime = left.time( );
	auto&& rightTime = right.time( );
	return comppareTime(leftTime, rightTime);
}

int comppareDate(QDate& left
	, QDate& right) {
	if( left.year( ) > right.year( ) )
		return 1;
	if( left.year( ) < right.year( ) )
		return -1;
	if( left.month( ) > right.month( ) )
		return 1;
	if( left.month( ) < right.month( ) )
		return -1;
	if( left.day( ) > right.day( ) )
		return 1;
	if( left.day( ) < right.day( ) )
		return -1;
	return 0;
}

int comppareDate(QDateTime& left
	, QDateTime& right) {
	auto&& leftDate = left.date( );
	auto&& rightDate = right.date( );
	return comppareDate(leftDate, rightDate);
}

int comppareTime(QTime& left
	, QTime& right) {
	if( left.hour( ) > right.hour( ) )
		return 1;
	if( left.hour( ) < right.hour( ) )
		return -1;
	if( left.minute( ) > right.minute( ) )
		return 1;
	if( left.minute( ) < right.minute( ) )
		return -1;
	if( left.second( ) > right.second( ) )
		return 1;
	if( left.second( ) < right.second( ) )
		return -1;
	if( left.msec( ) > right.msec( ) )
		return 1;
	if( left.msec( ) < right.msec( ) )
		return -1;
	return 0;
}

int comppareDateTime(QDateTime& left
	, QDateTime& right) {
	auto&& leftDate = left.date( );
	auto&& rightDate = right.date( );
	int&& comResult = comppareDate(leftDate, rightDate);
	if( comResult != 0 )
		return comResult;
	auto&& leftTime = left.time( );
	auto&& rightTime = right.time( );
	return comppareTime(leftTime, rightTime);
}

static const char* jsonDefaultJsonName = "./json/default.Json";
static QString defaultAbsoluteFilePath;

const QString* getDefaultAbsoluteFilePath( ) {
	if( defaultAbsoluteFilePath.isEmpty( ) ) {
		QFileInfo cominfo(jsonDefaultJsonName);
		defaultAbsoluteFilePath = cominfo.absoluteFilePath( );
	}
	return &defaultAbsoluteFilePath;
}

bool isDefaultSettingPath(QString absoluteFilePath) {
	if( defaultAbsoluteFilePath.isEmpty( ) ) {
		QFileInfo cominfo(jsonDefaultJsonName);
		defaultAbsoluteFilePath = cominfo.absoluteFilePath( );
	}
	if( defaultAbsoluteFilePath != absoluteFilePath ) {
		if( QFileInfo(absoluteFilePath).absoluteFilePath( ) == defaultAbsoluteFilePath )
			return true;
		return false;
	}
	return true;
}

int getSystemEnv(QMultiHash<QString, QString>& eventMap) {
	int result = 0;
	QStringList environment = QProcess::systemEnvironment( );
	int size = environment.size( );
	for( int index = 0;index < size;++index ) {
		QString chars = environment.at(index);
		QStringList env = chars.split("=");
		QString envName = env[0];
#if defined(Q_OS_WIN)
		QStringList value = env[1].split(";");
#elif defined(Q_OS_LINUX)
		QStringList value = env[1].split(":");
#endif
		int valueSize = value.size( );
		for( int valueIndex = 0;valueIndex < valueSize;++valueIndex ) {
			auto& eventValue = value.at(valueIndex);
			eventMap.insertMulti(envName, eventValue);
			++result;
		}
	}
	return result;
}
